﻿using DG.Tweening;
using ScFramework.Core;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;


public class InstanceManager : LogicModuleBase, InstanceInfo
{
    public static Player player = null;
    public GameObject Map = null;
    public static InstanceManager Instance = null;
    public Dictionary<TriData, MeshComp> Tris = new Dictionary<TriData, MeshComp>();
    public Vector2 DownVec => player.DownVec;

    public float Scale => player.Scale;

    public Player Player => player;

    public Dictionary<TriData, MeshComp> MapDic => Tris;

    public override void OnInit(object args)
    {
        base.OnInit(args);
        Instance = this;
    }
    public static void SetCollider(Triangle tri)
    {
        tri.RefreshMesh();
        for (int i = 0; i < tri.transform.childCount; i++)
        {
            var trans = tri.transform.GetChild(i);
            var pol = trans.gameObject.GetComponent<PolygonCollider2D>();
            List<Vector2> vecs = new List<Vector2>(tri.Tris[i].Points);
            if (Vector3.Cross(vecs[1] - vecs[0], vecs[2] - vecs[1]).z > 0)
            {
                var tp = vecs[2];
                vecs[2] = vecs[1];
                vecs[1] = tp;
            }
            pol.points = vecs.ToArray();
            trans.GetComponent<MeshComp>().SP = Specials.None;
        }
    }

    public void ChangeType(TriData tr, TriEnum type)
    {
        tr.Type = type;
        MapDic[tr].Tri = tr;
        MapDic[tr].gameObject.layer= LayerMask.NameToLayer("Ground");
    }

    public void Destory(TriData tri)
    {
        if (tri == null || MapDic.ContainsKey(tri) == false)
        {
            return;
        }
        var tp = MapDic[tri];
        if (tri.Equ(player.TriData) && player.IsFree == false&&tri.Type==TriEnum.Red)
        {
            Player.Alive = false;
        }
        MapDic.Remove(tri);
        //   GameObject.Destroy();
        ObjectPool.Recycle(tp.gameObject);
    }
    LocalData lstData = null;
    public void Restart()
    {
        ResetData(lstData);
    }
    public int KeyCnt;
    public void ResetData(LocalData data)
    {
        if (lstData != null||data.LevelID!=0)
        {

            var list = GameObject.FindObjectsOfType<Pop>();
            foreach (var x in list)
            {
                ObjectPool.Recycle(x);
            }
        }
        bool first = lstData != data;
        lstData = UnsafeTool.DeepCopyByJson(data);
        data = UnsafeTool.DeepCopyByJson(data);
        if (Map == null)
        {
            Map = GameObject.Find("Map");
        }
        if (player == null)
        {
            player = GameObject.Instantiate(Resources.Load<GameObject>("Prefabs/Player")).GetComponent<Player>();
            player.GetComponent<Slime>().Init();
            //          player.Tri=   data.Player.PlayerTri ;
        }
        //   Debug.Assert(data.Player.IsFree == false);
        player.Scale = data.Player.Scale;
        player._triData=(data.Player.PlayerTri);
        //   SetCollider(player.GetComponent<Triangle>());

        Map.GetComponent<Triangle>().Tris = data.Tris;
        SetCollider(Map.GetComponent<Triangle>());
        Tris.Clear();
        for (int i = 0; i < data.Tris.Count; i++)
        {
            Tris[data.Tris[i]] = Map.transform.GetChild(i).GetComponent<MeshComp>();
        }
        var lis = new List<TriData>(MapDic.Keys);
        KeyCnt = 0;
        foreach (var x in data.SpecialPoints)
        {
            if (x.Sp != Specials.Start)
            {
                var tri = lis.Find(s => s.ContainPoint((x.Pos)));
                MapDic[tri].SP = x.Sp;
                if (x.Sp == Specials.Key)
                {
                    KeyCnt++;
                }
            }
        }
        if (first)
        {
            Main.Instance.PopText($"This level requires {KeyCnt} keys(s).");
        }
        Player.Alive = true;
        if (data.Player.IsFree)
        {
            player.DownDir = data.Player.Down;
            player.ToFree();
            Map.transform.DOKill(false);
            Map.transform.localScale = Vector3.one;
        }
        else
        {
            player.ToTri(GetRelatedTri( data.Player.PlayerTri));
        }
    //    Debug.Log(player.transform.position+"!!"+player.GetComponent<Slam>().GetCenter());
    }

    public TriData GetRelatedTri(TriData tr)
    {
        foreach (var x in MapDic.Keys)
        {
            if (tr.Equ(x))
            {
                return x;
            }
        }
        return null;
    }
    public void NextLevel()
    {
        if (lstData.LevelID+1 < Main.Instance.Config.LevelCnt)
        {
            ResetData(JsonUtility.FromJson<LocalData>(ResourceManager.Instance.Load<TextAsset>("Map/Level_" + (lstData.LevelID + 1)).text));

        }
        else
        {
 
            Main.Instance.PopText("Thanks you for playing so far.\nPress 'R' to restart this level.");
        }
    }
}
public interface InstanceInfo : IModuleInnerInterface
{
    Vector2 DownVec { get; }
    float Scale { get; }
    Player Player { get; }

    Dictionary<TriData, MeshComp> MapDic { get; }

    TriData GetRelatedTri(TriData tr);
    void Destory(TriData tri);
    void ChangeType(TriData tr,TriEnum type);
}